package com.video.file.controller;


import com.video.api.client.UserClient;
import com.video.api.dto.InsertVideoDto;
import com.video.common.enumeration.AppHttpCodeEnum;
import com.video.common.result.ResponseResult;
import com.video.common.utils.DelFile;
import com.video.common.utils.UserContext;
import com.video.file.config.MinIOConfigProperties;
import com.video.file.domain.dto.DelMinioPathDto;
import com.video.file.service.FileStorageService;
import com.video.file.utils.FileCoverUtils;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/upload")
@RequiredArgsConstructor
public class FileController {

    private final FileStorageService fileStorageService;

    private final MinioClient minioClient;

    private final MinIOConfigProperties minIOConfigProperties;

    private final FileCoverUtils fileCoverUtils;

    private final UserClient userClient;


    /*
     * 上传图片
     * */
    @PostMapping("/image")
    public ResponseResult uploadImg(MultipartFile file) throws IOException {

        String url = fileStorageService.uploadImgFile("", file);
        return ResponseResult.okResult(url);
    }

    /*
     * 上传文件
     * */
    @PostMapping("/file")
    public ResponseResult uploadFile(MultipartFile file) throws IOException {

        String url = fileStorageService.uploadFile("", file);
        return ResponseResult.okResult(url);
    }

    /*
     * 切片上传文件
     * */

    @PostMapping("/chunk")
    public ResponseResult uploadChunk(@RequestParam("file") MultipartFile file,
                                      @RequestParam("chunkIndex") int chunkIndex,
                                      @RequestParam("chunkTotal") int chunkTotal,
                                      @RequestParam("identifier") String identifier) throws IOException {
        InputStream inputStream = file.getInputStream();

        try {
            String objectName = identifier + "/" + chunkIndex;
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(minIOConfigProperties.getBucket())
                            .object(objectName)
                            .stream(inputStream, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());
            return ResponseResult.okResult("Chunk " + chunkIndex + " uploaded successfully.");
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return ResponseResult.errorResult(1006, "Error: " + e.getMessage());
        } finally {
            inputStream.close();
        }
    }


    /*
     * 合并切片
     * */

    @PostMapping("/merge")
    @Transactional
    public ResponseResult mergeChunks(@RequestParam("identifier") String identifier,
                                      @RequestParam("chunkTotal") int chunkTotal) {
        try {
            // 拼接数据
            List<ComposeSource> sources = new ArrayList<>();
            for (int i = 0; i < chunkTotal; i++) {
                sources.add(ComposeSource.builder()
                        .bucket(minIOConfigProperties.getBucket())
                        .object(identifier + "/" + (i))
                        .build());
            }

            String newFileName = createNewFileName(identifier);
            // 合并上传
            minioClient.composeObject(
                    ComposeObjectArgs.builder()
                            .bucket(minIOConfigProperties.getBucket())
                            .object(newFileName)
                            .sources(sources)
                            .build());

            // 删除minio文件
            String mergeUrl = minIOConfigProperties.getReadPath() + "/" + minIOConfigProperties.getBucket() + "/" + newFileName;
            // 删除minio合并的文件夹
            DelFile.deleteFolder(minioClient, minIOConfigProperties.getBucket(), identifier + "/");
//            deleteFolder(minioClient, minIOConfigProperties.getBucket(), identifier + "/");


            return ResponseResult.okResult(mergeUrl);
        } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return ResponseResult.errorResult(1006, "Error: " + e.getMessage());
        }
    }

    /*
     * 上传完整视频信息
     * */
    @PostMapping("/video")
    @Transactional
    public ResponseResult uploadVideo(@RequestBody InsertVideoDto dto) throws ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException, InterruptedException {

        // 切片m3u8
        Map<String, String> urls = fileCoverUtils.uploadM3U8(dto.getVideoUrl());

        // 执行上传sql数据库
        InsertVideoDto build = InsertVideoDto.builder()
                .videoUrl(urls.get("videoUrl"))
                .type(dto.getType() != null? dto.getType() : 0)
                .isTop(dto.getIsTop() != null? dto.getIsTop():0)
                .userId(dto.getUserId()!=null? dto.getUserId():UserContext.getUser())
                .fileRemote(urls.get("fileRemote"))
                .title(dto.getTitle())
                .coverUrl(dto.getCoverUrl())
                .description(dto.getDescription())
                .build();

        System.out.println("打印的数据"+build);
        userClient.insert(build);
        // // 删除minio文件
        Thread.sleep(500);
        fileStorageService.delete(dto.getVideoUrl());
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /*
     * 删除文件
     * */
    @PostMapping("/delete")
    public ResponseResult deleteFile(@RequestBody DelMinioPathDto dto) {
        fileStorageService.delete(dto.getPath());
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /*
     * 生成新的文件名
     * */

    private String createNewFileName(String fileName) {
        // 获取文件名信息
        String prefix = fileName.substring(0, fileName.lastIndexOf("."));
        String randomVal = UUID.randomUUID().toString().replace("-", "").substring(0, 6);
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        return prefix + randomVal + suffix;
    }



    /*
     * 删除minio文件夹
     * */
    public static void deleteFolder(MinioClient minioClient, String bucketName, String folderPath) {
        try {
            // 列出文件夹中的所有对象
            Iterable<Result<Item>> results = minioClient.listObjects(
                    ListObjectsArgs.builder()
                            .bucket(bucketName)
                            .prefix(folderPath)
                            .recursive(true)
                            .build());

            // 遍历并删除每个对象
            for (Result<Item> result : results) {
                Item item = result.get();
                minioClient.removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(bucketName)
                                .object(item.objectName())
                                .build());
            }

            System.out.println("Folder and its contents deleted successfully.");
        } catch (MinioException | InvalidKeyException | NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
            System.err.println("Error deleting folder: " + e.getMessage());
        }
    }
}
